﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using YooAssetsSystem.Fsm;
using UnityEngine;
using UnityEngine.Networking;

namespace YooAssetsSystem.Patch
{
    /// <summary>
    /// 更新配置文件 没用
    /// </summary>
    public class UpdateConfigNode : BasePatchNode
    {
        private string ConfigDir => $"{Application.persistentDataPath}/Config";
        private string Manifest = "manifest.txt";

        private HashSet<UnityWebRequest> webRequestSet = new HashSet<UnityWebRequest>();
        private HashSet<UnityWebRequest> saveConfigSet = new HashSet<UnityWebRequest>();

        public override void OnEnter()
        {
#if UNITY_EDITOR
            // if (!InitRoot.init.editorUpdateConfig)
            // {
            //     machine.ChangeState<PatchDoneNode>();
            //     return;
            // }
#endif
            Debug.Log($"UpdateConfigNode: {shareData.updateResUrl}/{Manifest}");
            Owner.Event.ChangeStateEvent?.Invoke("正在更新配置文件");
            saveConfigSet.Clear();
            var asyncOperation = UnityWebRequest.Get($"{shareData.updateResUrl}/{Manifest}").SendWebRequest();
            asyncOperation.completed += delegate(AsyncOperation operation)
            {
                var webRequest = asyncOperation.webRequest;
                webRequestSet.Add(webRequest);
                if (webRequest.isDone && webRequest.downloadHandler.isDone)
                {
                    ParseManifest(webRequest.downloadHandler.text);
                }
                else if (!string.IsNullOrEmpty(webRequest.error))
                {
                    ClearConfigDir();
                    Debug.LogError($"更新配置失败, webRequest发生错误: {webRequest.uri}|{webRequest?.error}");
                    Owner.Event.UpdateFailedEvent?.Invoke($"{GetType().Name}失败, 停止更新");
                }
            };
        }

        private StringBuilder sb = new StringBuilder();

        public override void OnUpdate()
        {
            if (webRequestSet.Count == 0) return;
            if (webRequestSet.All(_ => _.isDone))
            {
                foreach (var webRequest in webRequestSet)
                {
                    if (saveConfigSet.Contains(webRequest)) continue;
                    if (webRequest.isDone && webRequest.downloadHandler.isDone)
                    {
                        saveConfigSet.Add(webRequest);
                        var text = webRequest.downloadHandler.text;
                        try
                        {
                            var dir = webRequest.url.Replace(shareData.updateResUrl, "");
                            var ss = dir.Split('/');
                            sb.Clear();
                            //如果配置表里面分了文件夹 此处依次创建文件夹层级
                            for (var i = 0; i < ss.Length - 1; i++)
                            {
                                if (string.IsNullOrEmpty(ss[i]) == false)
                                {
                                    sb.Append('/');
                                    sb.Append(ss[i]);
                                    dir = $"{ConfigDir}{sb}";
                                    if (!Directory.Exists(dir))
                                    {
                                        Directory.CreateDirectory(dir);
                                    }
                                }
                            }

                            var name = ss?.Last();
                            var file = $"{ConfigDir}{sb}/{name}";
                            File.WriteAllText(file, text);
                            Debug.Log($"SaveConfigDir: {file}");
                        }
                        catch (Exception e)
                        {
                            Debug.LogError($"SaveConfig: 保存配置文件错误: {e}");
                        }
                    }
                    else if (!string.IsNullOrEmpty(webRequest.error))
                    {
                        saveConfigSet.Add(webRequest);
                        Debug.LogError($"SaveConfig: webRequest发生错误:{webRequest.uri}|{webRequest?.error}");
                    }
                }

                if (saveConfigSet.Count == webRequestSet.Count)
                {
                    machine.ChangeState<PatchDoneNode>();
                }
            }
        }

        void ParseManifest(string manifest)
        {
            Debug.Log($"UpdateConfigNode:: ParseManifest: {manifest}");
            ClearConfigDir();
            // 使用换行符分割
            string[] ss = null;
            if (manifest.Contains("\r\n"))
            {
                ss = manifest.Split('\r', '\n');
            }
            else if (manifest.Contains("\r"))
            {
                ss = manifest.Split('\r');
            }
            else
            {
                ss = manifest.Split('\n');
            }

            var hashSet = new HashSet<string>();
            foreach (var s in ss)
            {
                var trim = s?.Trim();
                if (!string.IsNullOrEmpty(trim) && !trim.StartsWith("#"))
                {
                    hashSet.Add(trim);
                }
            }

            var sb = new StringBuilder();
            foreach (var s in hashSet)
            {
                sb.Append(s);
                sb.Append("\n");
                var url = $"{shareData.updateResUrl}/{s}";
                var asyncOperation = UnityWebRequest.Get(url).SendWebRequest();
                webRequestSet.Add(asyncOperation.webRequest);
            }

            if (sb.Length > 0)
            {
                Debug.Log($"UpdateConfigNode:: 即将更新的配置文件:\n{sb}");
            }
        }

        void ClearConfigDir()
        {
            var dir = ConfigDir;
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            var files = Directory.GetFiles(dir);
            foreach (var file in files)
            {
                File.Delete(file);
            }
        }

        public override void OnExit()
        {
            sb.Clear();
            foreach (var webRequest in webRequestSet)
            {
                webRequest.Dispose();
            }

            webRequestSet.Clear();
        }
    }
}